﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml.Linq;
using Renren.Helpers;
using Renren.Models;
using Renren.ViewModels;

namespace Renren.Services
{
    public static class FeedService
    {
        private static int page = 1;
        private static int count = 20;

        private static List<NewsModel> Parser(string xml)
        {
            var models = new List<NewsModel>();
            foreach (var element in XElement.Parse(xml).Elements())
            {
                var model = new NewsModel();
                model.FeedType = element.GetValue<FeedType>("feed_type");
                model.UpdateTime = element.GetValue<DateTime>("update_time");
                model.SourceId = element.GetValue<long>("source_id");
                model.PostId = element.GetValue<long>("post_id");
                model.ActorId = element.GetValue<long>("actor_id");
                model.Name = element.GetValue("name");
                model.HeadUrl = element.GetValue("headurl");
                model.CommentCount = element.GetValue("comments", "count");
                model.Prefix = element.GetValue("prefix");
                model.Description = element.GetValue("description");

                switch (model.FeedType)
                {
                    case FeedType.UpdateStatus:
                    //news.Message = element.GetValue("message");
                    //break;
                    case FeedType.ShareBlog:
                    case FeedType.SharePhoto:
                    case FeedType.UploadPhoto:
                        model.Message = element.GetValue("message");
                        model.Title = element.GetValue("title");
                        model.MediaList = new List<MediaModel>();
                        foreach (var subElement in element.Elements("attachment", "*"))
                        {
                            var media = new MediaModel();
                            media.Src = subElement.GetValue("src");
                            media.Href = subElement.GetValue("href");
                            media.MediaId = subElement.GetValue("media_id");
                            media.OwnerId = subElement.GetValue("owner_id");
                            media.MediaType = subElement.GetValue("media_type");
                            media.Content = subElement.GetValue("content");
                            model.MediaList.Add(media);
                        }
                        break;
                    default:
                        model.Title = element.GetValue("title");
                        break;
                }

                model.CommentList = new ObservableCollection<CommentModel>();
                foreach (var subElement in element.Elements("comments", "comment"))
                {
                    var comment = new CommentModel();
                    comment.UpdateTime = subElement.GetValue<DateTime>("time");
                    comment.CommentId = subElement.GetValue<long>("comment_id");
                    comment.UserId = subElement.GetValue<long>("uid");
                    comment.Text = subElement.GetValue("text");
                    comment.Name = subElement.GetValue("name");
                    comment.HeadUrl = subElement.GetValue("headurl");
                    model.CommentList.Add(comment);
                }
                models.Add(model);
            }
            return models;
        }
        
        public static void AddComment(NewsModel news, string content)
        {
            if (news != null && content != null)
            {
                var parameters = new Dictionary<string, string>();
                parameters.Add("content", content);
                switch (news.FeedType)
                {
                    case FeedType.UpdateStatus:
                        parameters.Add("method", "status.addComment");
                        parameters.Add("status_id", news.SourceId.ToString());
                        parameters.Add("owner_id", news.ActorId.ToString());
                        break;
                    case FeedType.PostBlog:
                        parameters.Add("method", "blog.addComment");
                        parameters.Add("id", news.SourceId.ToString());
                        parameters.Add("uid", news.ActorId.ToString());
                        break;
                    case FeedType.UploadPhoto:
                        parameters.Add("method", "photos.addComment");
                        parameters.Add("uid", news.ActorId.ToString());
                        parameters.Add("aid", news.SourceId.ToString());
                        break;
                    case FeedType.ShareVideo:
                    case FeedType.ShareLink:
                    case FeedType.ShareMusic:
                    case FeedType.ShareAlbum:
                    case FeedType.SharePhoto:
                    case FeedType.ShareBlog:
                        parameters.Add("method", "share.addComment");
                        parameters.Add("share_id", news.SourceId.ToString());
                        parameters.Add("user_id", news.ActorId.ToString());
                        break;
                    default:
                        return;
                }
                Service.SendRequest(parameters, null);
            }
        }

        public static void GetComment(NewsModel news, int page = 1, int count = 20)
        {
            var parameters = new Dictionary<string, string>();
            switch (news.FeedType)
            {
                case FeedType.UpdateStatus:
                    parameters.Add("method", "status.getComment");
                    parameters.Add("status_id", news.SourceId.ToString());
                    parameters.Add("owner_id", news.ActorId.ToString());
                    break;
                case FeedType.PostBlog:
                    parameters.Add("method", "blog.getComments");
                    parameters.Add("id", news.SourceId.ToString());
                    parameters.Add("uid", news.ActorId.ToString());
                    break;
                case FeedType.UploadPhoto:
                    parameters.Add("method", "photos.getComments");
                    parameters.Add("uid", news.ActorId.ToString());
                    parameters.Add("aid", news.SourceId.ToString());
                    break;
                case FeedType.ShareVideo:
                case FeedType.ShareLink:
                case FeedType.ShareMusic:
                case FeedType.ShareAlbum:
                case FeedType.SharePhoto:
                case FeedType.ShareBlog:
                    parameters.Add("method", "share.getComments");
                    parameters.Add("share_id", news.SourceId.ToString());
                    parameters.Add("user_id", news.ActorId.ToString());
                    break;
                default:
                    return;
            }
            parameters.Add("page", page.ToString());
            parameters.Add("count", count.ToString());
            Service.SendRequest(
                parameters,
                result =>
                {
                    news.CommentList.Clear();
                    var root = XElement.Parse(result);
                    switch (news.FeedType)
                    {
                        case FeedType.UpdateStatus:
                            foreach (var element in root.Elements())
                            {
                                var comment = new CommentModel();
                                comment.UpdateTime = element.GetValue<DateTime>("time");
                                comment.CommentId = element.GetValue<long>("comment_id");
                                comment.UserId = element.GetValue<long>("uid");
                                comment.Text = element.GetValue("text");
                                comment.Name = element.GetValue("name");
                                comment.HeadUrl = element.GetValue("tinyurl");
                                news.CommentList.Add(comment);
                            }
                            break;
                        case FeedType.PostBlog:
                            foreach (var element in root.Elements())
                            {
                                var comment = new CommentModel();
                                comment.UpdateTime = element.GetValue<DateTime>("time");
                                comment.CommentId = element.GetValue<long>("id");
                                comment.UserId = element.GetValue<long>("uid");
                                comment.Text = element.GetValue("content");
                                comment.Name = element.GetValue("name");
                                comment.HeadUrl = element.GetValue("headurl");
                                news.CommentList.Add(comment);
                            }
                            break;
                        case FeedType.UploadPhoto:
                            foreach (var element in root.Elements())
                            {
                                var comment = new CommentModel();
                                comment.UpdateTime = element.GetValue<DateTime>("time");
                                comment.CommentId = element.GetValue<long>("comment_id");
                                comment.UserId = element.GetValue<long>("uid");
                                comment.Text = element.GetValue("text");
                                comment.Name = element.GetValue("name");
                                comment.HeadUrl = element.GetValue("headurl");
                                news.CommentList.Add(comment);
                            }
                            break;
                        case FeedType.ShareBlog:
                        case FeedType.SharePhoto:
                        case FeedType.ShareAlbum:
                        case FeedType.ShareVideo:
                        case FeedType.ShareLink:
                        case FeedType.ShareMusic:
                            foreach (var element in root.Elements("comments", "*"))
                            {
                                var comment = new CommentModel();
                                comment.UpdateTime = element.GetValue<DateTime>("time");
                                comment.CommentId = element.GetValue<long>("id");
                                comment.UserId = element.GetValue<long>("uid");
                                comment.Text = element.GetValue("content");
                                comment.Name = element.GetValue("name");
                                comment.HeadUrl = element.GetValue("headurl");
                                news.CommentList.Add(comment);
                            }
                            break;
                    }
                });
        }

        public static void GetFeed(
            CachedCollection<NewsViewModel, NewsModel> newsList,
            RequestType requestType = RequestType.GetInit,
            Action callback = null,
            long userId = 0)
        {
            if (newsList.Count == 0)
            {
                var models = Service.FetchStorage<NewsModel>(ActionType.FeedGet, Parser);
                if (models != null)
                {
                    newsList.Refresh(models);
                }
            }
            var parameters = new Dictionary<string, string>();
            parameters.Add("method", "feed.get");
            parameters.Add("type", "10,20,21,30,32,33,34,40,50,51");
            if (userId != 0)
            {
                parameters.Add("uid", userId.ToString());
            }
            if (requestType == RequestType.GetInit)
            {
                page = 1;
                count = 10;
            }
            else
            {
                count = 20;
            }
            parameters.Add("page", page.ToString());
            parameters.Add("count", count.ToString());
            Service.SendRequest(
                parameters,
                result =>
                {
                    var models = Parser(result);
                    if (requestType == RequestType.GetInit)
                    {
                        page = 2;
                        newsList.Refresh(models);
                        Service.WritebackStorage(ActionType.FeedGet, result);
                    }
                    else
                    {
                        page++;
                        if (!newsList.Add(models))
                        {
                            GetFeed(newsList, requestType);
                        }
                    }
                    if (callback != null)
                    {
                        callback();
                    }
                });
        }
    }
}
